package com.twotwoshop.gateway.user.config;

import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;


@Configuration
public class RateLimiterConfig {


    //**功能**：根据请求的 API 路径进行限流。
    //**实现**：从请求中获取请求路径，并将其作为限流的键。
    //**用途**：适用于基于 API 路径的限流策略，防止某个 API 被过多请求。
    @Bean
    @Primary
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest()
                .getRemoteAddress()
                .getHostName());
    }

    // 如果需要其他限流策略，可以添加新的方法但不要标记为@Bean
    public KeyResolver userKeyResolver() {
        return exchange -> {
            String authorization = exchange.getRequest().getHeaders().getFirst("Authorization");
            String token = null;
            if (StringUtils.isNotBlank(authorization) && authorization.startsWith("Bearer ")) {
                token = authorization.substring(7);
            }
            return Mono.just(StringUtils.defaultIfBlank(token, "default-token"));
        };
    }
}


/*
@Configuration
public class RateLimiterConfig {


    //**功能**：根据请求的 IP 地址进行限流。
    //**实现**：从请求中获取远程地址的主机名，并将其作为限流的键。
    //**用途**：适用于基于客户端 IP 地址的限流策略，防止单个 IP 过多请求。
    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }


    //**功能**：根据请求的 API 路径进行限流。
    //**实现**：从请求中获取请求路径，并将其作为限流的键。
    //**用途**：适用于基于 API 路径的限流策略，防止某个 API 被过多请求。
    @Bean
    public KeyResolver apiKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getPath().value());
    }


    //**功能**：根据请求头中的 `token` 进行限流。
    //**实现**：从请求头中获取 `token`，并将其作为限流的键。
    //**用途**：适用于基于用户身份的限流策略，防止单个用户过多请求。
    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> {
            // 从Header中获取Authorization
            String authorization = exchange.getRequest().getHeaders().getFirst("Authorization");
            String token = null;
            if (StringUtils.isNotBlank(authorization) && authorization.startsWith("Bearer ")) {
                token = authorization.substring(7);
            }
            // 如果token为空，返回一个默认值或抛出异常
            return Mono.just(StringUtils.defaultIfBlank(token, "default-token"));
        };
    }
}
*/


/**
 * 这个代码片段是一个 Spring Cloud Gateway 的配置类，用于定义不同的 `KeyResolver`，这些 `KeyResolver` 用于在限流（Rate Limiting）策略中确定唯一的键。限流是为了防止服务过载，通过限制请求的速率来保护服务。以下是对每个 `KeyResolver` 的解释：
 *
 * ### 1. `ipKeyResolver`
 *
 * ```java
 * @Bean
 * public KeyResolver ipKeyResolver() {
 *     return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
 * }
 * ```
 *
 * - **功能**：根据请求的 IP 地址进行限流。
 * - **实现**：从请求中获取远程地址的主机名，并将其作为限流的键。
 * - **用途**：适用于基于客户端 IP 地址的限流策略，防止单个 IP 过多请求。
 *
 * ### 2. `apiKeyResolver`
 *
 * ```java
 * @Bean
 * public KeyResolver apiKeyResolver() {
 *     return exchange -> Mono.just(exchange.getRequest().getPath().value());
 * }
 * ```
 *
 * - **功能**：根据请求的 API 路径进行限流。
 * - **实现**：从请求中获取请求路径，并将其作为限流的键。
 * - **用途**：适用于基于 API 路径的限流策略，防止某个 API 被过多请求。
 *
 * ### 3. `userKeyResolver`
 *
 * ```java
 * @Bean
 * public KeyResolver userKeyResolver() {
 *     return exchange -> Mono.just(exchange.getRequest().getHeaders().getFirst("token"));
 * }
 * ```
 *
 * - **功能**：根据请求头中的 `token` 进行限流。
 * - **实现**：从请求头中获取 `token`，并将其作为限流的键。
 * - **用途**：适用于基于用户身份的限流策略，防止单个用户过多请求。
 *
 * ### 总结
 *
 * - **KeyResolver**：是 Spring Cloud Gateway 中用于限流的关键组件。它们用于从请求中提取信息，以确定限流的唯一键。
 * - **使用场景**：可以根据不同的业务需求选择不同的 `KeyResolver`，例如按 IP、API 路径或用户进行限流。
 * - **灵活性**：可以根据需要自定义 `KeyResolver`，以实现更复杂的限流策略。
 *
 * 这些 `KeyResolver` 可以在限流配置中使用，以便在不同的维度上进行限流控制。
 */